#include "pch.h"
#include "Model.h"
namespace mini
{
	CModel::CModel()
	{
		mResourceType = Model;
	}
	CModel::~CModel()
	{
		for( auto& item : mTextures)
		{
			for (auto& child : item.second)
			{
				SafeRelease(child.second);
			}
		}
		mpMeshesInfo.clear();
		SafeDeleteArray(mpSdkMeshInfo);
	}

	void CModel::pushMeshUnit(CMeshUnit* pMeshUnit)
	{
		if (nullptr != pMeshUnit)
		{
			MeshInfo info;
			info.pMeshUnit = pMeshUnit;
			UINT32 Id = pMeshUnit->getBuildMesh()->getResourceID();
			mpMeshesInfo[Id] = info;	
		}
	}

	void CModel::pushTexture(int nGround, const std::string& name, CResourceBase* pResource)
	{
		if (pResource->getResourceType() == Texture)
		{
			mTextures[nGround][name] = dynamic_cast<CTexture*>(pResource);
			pResource->AddRef();
		}
	}

	CModel::MeshInfo* CModel::getMeshInfoPtr(CMesh* pMesh)
	{
		if (nullptr != pMesh)
		{
			for (auto& item : mpMeshesInfo)
			{
				if ((item.second).pMeshUnit->getBuildMesh() == pMesh)
				{
					return &(item.second);
				}
			}
		}
		return nullptr;
	}

	const std::map<UINT32, mini::CModel::MeshInfo>& CModel::getMeshInfoMap() const 
	{
		return mpMeshesInfo;
	}

	BYTE* CModel::getSdkMeshData()
	{
		return mpSdkMeshInfo;
	}

	const std::map<std::string, CTexture*>& CModel::getGroundTextures(int nIndex)
	{
		return mTextures[nIndex];
	}

	void CModel::mergeBoundBox()
	{
		mBoundBox.reset();
		CPoint3F fMin(FLT_MAX, FLT_MAX, FLT_MAX);
		CPoint3F fMax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
		for( auto& item : mpMeshesInfo )
		{
			if (nullptr != (item.second).pMeshUnit)
			{
				CBoundBox& box = (item.second).pMeshUnit->getBoundBox();
				if (box.mOriginalMaxPos.x > fMax.x)
				{
					fMax.x = box.mOriginalMaxPos.x;
				}
				if (box.mOriginalMaxPos.y > fMax.y)
				{
					fMax.y = box.mOriginalMaxPos.y;
				}
				if (box.mOriginalMaxPos.z > fMax.z)
				{
					fMax.z = box.mOriginalMaxPos.z;
				}

				if (box.mOriginalMinPos.x , fMin.x)
				{
					fMin.x = box.mOriginalMinPos.x;
				}
				if (box.mOriginalMinPos.y < fMin.y)
				{
					fMin.y = box.mOriginalMinPos.y;
				}
				if (box.mOriginalMinPos.z < fMin.z)
				{
					fMin.z = box.mOriginalMinPos.z;
				}
			}
		}
		mBoundBox.setBoundBoxRange(fMin, fMax);
	}

	void CModel::popMesh(CMesh* pMesh)
	{
		if (nullptr != pMesh)
		{
			popMesh(pMesh->getResourceID());
		}
	}

	void CModel::popMesh(UINT32 resId)
	{
		auto item = mpMeshesInfo.begin();
		auto iEnd = mpMeshesInfo.end();
		for( ; item != iEnd; ++item )
		{
			if ( (item->second).pMeshUnit->getBuildMesh()->getResourceID() == resId)
			{
				mpMeshesInfo.erase(item);
				break;
			}
		}
	}

	void CModel::popMesh(const std::string& szMeshName)
	{
		auto item = mpMeshesInfo.begin();
		auto itemEnd = mpMeshesInfo.end();
		while (item != itemEnd)
		{
			if ((item->second).pMeshUnit->getBuildMesh()->getResourceName() == szMeshName)
			{
				item = mpMeshesInfo.erase(item);
			}
		}
	}

	void CModel::buildMaterialUnit(const std::string& strMaterial)
	{
		SafeDelete(mpMaterialUnit);
		mpMaterialUnit = new CMaterialUnit;
		mpMaterialUnit->setUnitFile(strMaterial);
		mpMaterialUnit->onInitialise();
	}

}